﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using Skylabs.Net;

namespace Skylabs.Breeze
{
    public class FileReceiver : IEquatable<FileReceiver>,IEquatable<String>
    {
        public string LocalFileName { get; set; }
        public string FileName { get; set; }
        public long TotalSize { get; set; }
        public string Hash { get; set; }
        public bool CreatedBlankFile = false;
        public FileStream File;
        public int TotalPacketsReceived = 0;
        public long TotalBytesReceived { get; private set; }
        public List<Client> Clients { get; set; } 
        public int Progress
        {
            get
            {
                return (int)(((double)TotalPacketsReceived / (double)TotalSize) * 100d);
            }
        }
        public FileReceiver(string fname)
        {
            FileName = fname;
            Clients = new List<Client>();

        }
        public void Start(long size, string hash)
        {
            TotalSize = size;
            Program.ServerTrace.TraceInformation("Starting file transfer");
            string path = Environment.ExpandEnvironmentVariables(Skylabs.Breeze.Properties.Settings.Default.dod);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            path = System.IO.Path.Combine(path, FileName);
            Program.ServerTrace.TraceInformation("FileName:{0}\nSize:{1}\nLocalPath:{2}", FileName, size.ToString(), path);
            Hash = hash;
            //File = MemoryMappedFile.CreateFromFile(path, FileMode.Create, fname, size,MemoryMappedFileAccess.ReadWrite);
            File = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
            //File.Seek(TotalSize - 1, SeekOrigin.Begin);
            TotalBytesReceived = 0;            
        }
        public void AddPart(long position,int length,byte[] data)
        {
            lock (this)
            {
                File.Seek(position, SeekOrigin.Begin);
                File.Write(data,0,length);
                File.Flush();
                TotalPacketsReceived++;
                TotalBytesReceived += length;
            }
        }
        public void ClientDone(Client c)
        {
            lock (Clients)
            {
                //Program.ServerTrace.TraceInformation("Client disconnected");
                c.Close(DisconnectReason.CleanDisconnect);
                Clients.Remove(c);
                if (Clients.Count == 0)
                {
                    Close();
                    Server.TransferDone(this);
                }
            }
        }
        public void Close()
        {
                try
                {
                    File.Close();
                    File.Dispose();
                }
                catch (Exception e)
                {
                    Program.ServerTrace.TraceEvent(TraceEventType.Error, 0, e.Message);
                }
        }
        public bool Equals(FileReceiver other)
        {
            return other.FileName.Equals(FileName);
        }

        public bool Equals(string other)
        {
            return other.Equals(FileName);
        }
    }
}
